package xyz.hubery.feign;

import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

@Slf4j
@Component
public class ClientCredentialsFeignInterceptor implements RequestInterceptor {

    @Value("${security.oauth2.client.access-token-uri:http://localhost:9999/oauth/token}")
    private String accessTokenUri;

    @Value("${security.oauth2.client.client-id:inside-app}")
    private String clientId;

    @Value("${security.oauth2.client.client-secret:inside-secret}")
    private String clientSecret;

    private String cachedToken;

    private long tokenExpiryTime;

    @Override
    public void apply(RequestTemplate template) {
        String token = getClientCredentialsToken();
        if (token != null) {
            template.header(HttpHeaders.AUTHORIZATION, "Bearer " + token);
            log.debug("已添加客户端凭证Token到请求头");
        } else {
            log.error("无法获取客户端凭证Token");
        }
    }

    private String getClientCredentialsToken() {
        // 如果token未过期，使用缓存的token
        if (cachedToken != null && System.currentTimeMillis() < tokenExpiryTime) {
            return cachedToken;
        }

        try {
            RestTemplate restTemplate = new RestTemplate();

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            headers.setBasicAuth(clientId, clientSecret);

            MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
            body.add("grant_type", "client_credentials");
            body.add("scope", "all");

            HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(body, headers);

            ResponseEntity<TokenResponse> response = restTemplate.postForEntity(
                    accessTokenUri, request, TokenResponse.class);

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                TokenResponse tokenResponse = response.getBody();
                cachedToken = tokenResponse.getAccess_token();
                // 设置token过期时间（提前5分钟刷新）
                tokenExpiryTime = System.currentTimeMillis() + (tokenResponse.getExpires_in() - 300) * 1000;

                log.info("成功获取客户端凭证Token, 有效期: {}秒", tokenResponse.getExpires_in());
                return cachedToken;
            }
        } catch (Exception e) {
            log.error("获取客户端凭证Token失败", e);
        }

        return null;
    }

    // Token响应DTO
    private static class TokenResponse {
        private String access_token;
        private String token_type;
        private Long expires_in;
        private String scope;

        // getters and setters
        public String getAccess_token() { return access_token; }
        public void setAccess_token(String access_token) { this.access_token = access_token; }
        public String getToken_type() { return token_type; }
        public void setToken_type(String token_type) { this.token_type = token_type; }
        public Long getExpires_in() { return expires_in; }
        public void setExpires_in(Long expires_in) { this.expires_in = expires_in; }
        public String getScope() { return scope; }
        public void setScope(String scope) { this.scope = scope; }
    }
}